home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Tools / Mesa-1.2.1 / src-aux / shapes.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-07-05  |  27.1 KB  |  1,059 lines

  1. /* shapes.c */
  2.  
  3.  
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <math.h>
  7. #include <GL/gl.h>
  8. #include <GL/glu.h>
  9. #include "glaux.h"
  10. #include "3d.h"
  11.  
  12.  
  13.  
  14. #define SPHEREWIRE    0
  15. #define CUBEWIRE    1
  16. #define BOXWIRE        2
  17. #define TORUSWIRE    3
  18. #define CYLINDERWIRE    4
  19. #define ICOSAWIRE    5
  20. #define OCTAWIRE    6
  21. #define TETRAWIRE    7
  22. #define DODECAWIRE    8
  23. #define CONEWIRE    9
  24. #define SPHERESOLID    10
  25. #define CUBESOLID    11
  26. #define BOXSOLID    12
  27. #define TORUSSOLID    13
  28. #define CYLINDERSOLID    14
  29. #define ICOSASOLID    15
  30. #define OCTASOLID    16
  31. #define TETRASOLID    17
  32. #define DODECASOLID    18
  33. #define CONESOLID    19
  34.  
  35. #define PI 3.1415926535897
  36.  
  37. /*    structure for each geometric object    */
  38. typedef struct model {
  39.     GLuint list;    /*  display list to render object   */
  40.     struct model *ptr;    /*  pointer to next object    */
  41.     int numParam;    /*  # of parameters        */
  42.     GLdouble *params;    /*  array with parameters    */
  43. } MODEL, *MODELPTR;
  44.  
  45. /*    array of linked lists--used to keep track of display lists 
  46.  *    for each different type of geometric object.
  47.  */
  48. static MODELPTR lists[25] = {
  49.     NULL, NULL, NULL, NULL, NULL,
  50.     NULL, NULL, NULL, NULL, NULL,
  51.     NULL, NULL, NULL, NULL, NULL,
  52.     NULL, NULL, NULL, NULL, NULL,
  53.     NULL, NULL, NULL, NULL, NULL
  54. };
  55.  
  56. GLuint findList (int lindex, GLdouble *paramArray, int size);
  57. int compareParams (GLdouble *oneArray, GLdouble *twoArray, int size);
  58. GLuint makeModelPtr (int lindex, GLdouble *sizeArray, int count);
  59.  
  60. static void drawbox(GLdouble, GLdouble, GLdouble, 
  61.     GLdouble, GLdouble, GLdouble, GLenum);
  62. static void doughnut(GLdouble, GLdouble, GLint, GLint, GLenum);
  63. static void icosahedron(GLdouble *, GLdouble, GLenum);
  64. static void octahedron(GLdouble *, GLdouble, GLenum);
  65. static void tetrahedron(GLdouble *, GLdouble, GLenum);
  66. static void subdivide(int, GLdouble *, GLdouble *, GLdouble *,
  67.     GLdouble *, GLdouble, GLenum, int);
  68. static void drawtriangle(int, int, int,
  69.     GLdouble *, GLdouble, GLenum, int);
  70. static void recorditem(GLdouble *, GLdouble *, GLdouble *,
  71.     GLdouble *, GLdouble, GLenum, int);
  72. static void initdodec(void);
  73. static void dodecahedron(GLdouble *, GLdouble, GLenum);
  74. static void pentagon(int, int, int, int, int, GLenum);
  75.  
  76.  
  77. /*  Render wire frame or solid sphere.  If no display list with
  78.  *  the current model size exists, create a new display list.
  79.  */
  80. void auxWireSphere (GLdouble radius)
  81. {
  82.     GLUquadricObj *quadObj;
  83.     GLdouble *sizeArray;
  84.     GLuint displayList;
  85.  
  86.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
  87.     *sizeArray = radius;
  88.     displayList = findList (SPHEREWIRE, sizeArray, 1);
  89.  
  90.     if (displayList == 0) {
  91.     glNewList(makeModelPtr (SPHEREWIRE, sizeArray, 1),
  92.         GL_COMPILE_AND_EXECUTE);
  93.         quadObj = gluNewQuadric ();
  94.         gluQuadricDrawStyle (quadObj, GLU_LINE);
  95.         gluSphere (quadObj, radius, 16, 16);
  96.     glEndList();
  97.     }
  98.     else {
  99.     glCallList(displayList);
  100.     free (sizeArray);
  101.     }
  102. }
  103.  
  104. void auxSolidSphere (GLdouble radius)
  105. {
  106.     GLUquadricObj *quadObj;
  107.     GLdouble *sizeArray;
  108.     GLuint displayList;
  109.  
  110.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
  111.     *sizeArray = radius;
  112.     displayList = findList (SPHERESOLID, sizeArray, 1);
  113.  
  114.     if (displayList == 0) {
  115.     glNewList(makeModelPtr (SPHERESOLID, sizeArray, 1),
  116.         GL_COMPILE_AND_EXECUTE);
  117.         quadObj = gluNewQuadric ();
  118.         gluQuadricDrawStyle (quadObj, GLU_FILL);
  119.         gluQuadricNormals (quadObj, GLU_SMOOTH);
  120.         gluSphere (quadObj, radius, 16, 16);
  121.     glEndList();
  122.     }
  123.     else {
  124.     glCallList(displayList);
  125.     free (sizeArray);
  126.     }
  127. }
  128.  
  129. /*  Render wire frame or solid cube.  If no display list with
  130.  *  the current model size exists, create a new display list.
  131.  */
  132. void auxWireCube (GLdouble size)
  133. {
  134.     GLdouble *sizeArray;
  135.     GLuint displayList;
  136.  
  137.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
  138.     *sizeArray = size;
  139.     displayList = findList (CUBEWIRE, sizeArray, 1);
  140.  
  141.     if (displayList == 0) {
  142.     glNewList(makeModelPtr (CUBEWIRE, sizeArray, 1),
  143.         GL_COMPILE_AND_EXECUTE);
  144.         drawbox(-size/2., size/2., -size/2., size/2., 
  145.         -size/2., size/2., GL_LINE_LOOP);
  146.     glEndList();
  147.     }
  148.     else {
  149.     glCallList(displayList);
  150.     free (sizeArray);
  151.     }
  152. }
  153.  
  154. void auxSolidCube (GLdouble size)
  155. {
  156.     GLdouble *sizeArray;
  157.     GLuint displayList;
  158.  
  159.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
  160.     *sizeArray = size;
  161.     displayList = findList (CUBESOLID, sizeArray, 1);
  162.  
  163.     if (displayList == 0) {
  164.     glNewList(makeModelPtr (CUBESOLID, sizeArray, 1),
  165.         GL_COMPILE_AND_EXECUTE);
  166.         drawbox(-size/2., size/2., -size/2., size/2., 
  167.         -size/2., size/2., GL_QUADS);
  168.     glEndList();
  169.     }
  170.     else {
  171.     glCallList(displayList);
  172.     free (sizeArray);
  173.     }
  174. }
  175.  
  176. /*  Render wire frame or solid cube.  If no display list with
  177.  *  the current model size exists, create a new display list.
  178.  */
  179. void auxWireBox (GLdouble width, GLdouble height, GLdouble depth)
  180. {
  181.     GLdouble *sizeArray, *tmp;
  182.     GLuint displayList;
  183.  
  184.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 3);
  185.     tmp = sizeArray;
  186.     *tmp++ = width;
  187.     *tmp++ = height;
  188.     *tmp++ = depth;
  189.     displayList = findList (BOXWIRE, sizeArray, 3);
  190.  
  191.     if (displayList == 0) {
  192.     glNewList(makeModelPtr (BOXWIRE, sizeArray, 3),
  193.         GL_COMPILE_AND_EXECUTE);
  194.         drawbox(-width/2., width/2., -height/2., height/2., 
  195.         -depth/2., depth/2., GL_LINE_LOOP);
  196.     glEndList();
  197.     }
  198.     else {
  199.     glCallList(displayList);
  200.     free (sizeArray);
  201.     }
  202. }
  203.  
  204. void auxSolidBox (GLdouble width, GLdouble height, GLdouble depth)
  205. {
  206.     GLdouble *sizeArray, *tmp;
  207.     GLuint displayList;
  208.  
  209.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 3);
  210.     tmp = sizeArray;
  211.     *tmp++ = width;
  212.     *tmp++ = height;
  213.     *tmp++ = depth;
  214.     displayList = findList (BOXSOLID, sizeArray, 3);
  215.  
  216.     if (displayList == 0) {
  217.     glNewList(makeModelPtr (BOXSOLID, sizeArray, 3),
  218.         GL_COMPILE_AND_EXECUTE);
  219.         drawbox(-width/2., width/2., -height/2., height/2., 
  220.         -depth/2., depth/2., GL_QUADS);
  221.     glEndList();
  222.     }
  223.     else {
  224.     glCallList(displayList);
  225.     free (sizeArray);
  226.     }
  227. }
  228.  
  229. /*  Render wire frame or solid tori.  If no display list with
  230.  *  the current model size exists, create a new display list.
  231.  */
  232. void auxWireTorus (GLdouble innerRadius, GLdouble outerRadius)
  233. {
  234.     GLdouble *sizeArray, *tmp;
  235.     GLuint displayList;
  236.  
  237.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 2);
  238.     tmp = sizeArray;
  239.     *tmp++ = innerRadius;
  240.     *tmp++ = outerRadius;
  241.     displayList = findList (TORUSWIRE, sizeArray, 2);
  242.  
  243.     if (displayList == 0) {
  244.     glNewList(makeModelPtr (TORUSWIRE, sizeArray, 2),
  245.         GL_COMPILE_AND_EXECUTE);
  246.         doughnut(innerRadius, outerRadius, 5, 10, GL_LINE_LOOP);
  247.     glEndList();
  248.     }
  249.     else {
  250.     glCallList(displayList);
  251.     free (sizeArray);
  252.     }
  253. }
  254.  
  255. void auxSolidTorus (GLdouble innerRadius, GLdouble outerRadius)
  256. {
  257.     GLdouble *sizeArray, *tmp;
  258.     GLuint displayList;
  259.  
  260.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 2);
  261.     tmp = sizeArray;
  262.     *tmp++ = innerRadius;
  263.     *tmp++ = outerRadius;
  264.     displayList = findList (TORUSSOLID, sizeArray, 2);
  265.  
  266.     if (displayList == 0) {
  267.     glNewList(makeModelPtr (TORUSSOLID, sizeArray, 2),
  268.         GL_COMPILE_AND_EXECUTE);
  269.         doughnut(innerRadius, outerRadius, 8, 15, GL_QUADS);
  270.     glEndList();
  271.     }
  272.     else {
  273.     glCallList(displayList);
  274.     free (sizeArray);
  275.     }
  276. }
  277.  
  278. /*  Render wire frame or solid cylinders.  If no display list with
  279.  *  the current model size exists, create a new display list.
  280.  */
  281. void auxWireCylinder (GLdouble radius, GLdouble height)
  282. {
  283.     GLUquadricObj *quadObj;
  284.     GLdouble *sizeArray, *tmp;
  285.     GLuint displayList;
  286.  
  287.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 2);
  288.     tmp = sizeArray;
  289.     *tmp++ = radius;
  290.     *tmp++ = height;
  291.     displayList = findList (CYLINDERWIRE, sizeArray, 2);
  292.  
  293.     if (displayList == 0) {
  294.     glNewList(makeModelPtr (CYLINDERWIRE, sizeArray, 2),
  295.         GL_COMPILE_AND_EXECUTE);
  296.         glPushMatrix ();
  297.         glRotatef (90.0, 1.0, 0.0, 0.0);
  298.         glTranslatef (0.0, 0.0, -1.0);
  299.         quadObj = gluNewQuadric ();
  300.         gluQuadricDrawStyle (quadObj, GLU_LINE);
  301.         gluCylinder (quadObj, radius, radius, height, 12, 2);
  302.         glPopMatrix ();
  303.     glEndList();
  304.     }
  305.     else {
  306.     glCallList(displayList);
  307.     free (sizeArray);
  308.     }
  309. }
  310.  
  311. void auxSolidCylinder (GLdouble radius, GLdouble height)
  312. {
  313.     GLUquadricObj *quadObj;
  314.     GLdouble *sizeArray, *tmp;
  315.     GLuint displayList;
  316.  
  317.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 2);
  318.     tmp = sizeArray;
  319.     *tmp++ = radius;
  320.     *tmp++ = height;
  321.     displayList = findList (CYLINDERWIRE, sizeArray, 2);
  322.  
  323.     if (displayList == 0) {
  324.     glNewList(makeModelPtr (CYLINDERWIRE, sizeArray, 2),
  325.         GL_COMPILE_AND_EXECUTE);
  326.         glPushMatrix ();
  327.         glRotatef (90.0, 1.0, 0.0, 0.0);
  328.         glTranslatef (0.0, 0.0, -1.0);
  329.         quadObj = gluNewQuadric ();
  330.         gluQuadricDrawStyle (quadObj, GLU_FILL);
  331.         gluQuadricNormals (quadObj, GLU_SMOOTH);
  332.         gluCylinder (quadObj, radius, radius, height, 12, 2);
  333.         glPopMatrix ();
  334.     glEndList();
  335.     }
  336.     else {
  337.     glCallList(displayList);
  338.     free (sizeArray);
  339.     }
  340. }
  341.  
  342. /*  Render wire frame or solid icosahedra.  If no display list with
  343.  *  the current model size exists, create a new display list.
  344.  */
  345. void auxWireIcosahedron (GLdouble radius)
  346. {
  347.     GLdouble *sizeArray;
  348.     GLuint displayList;
  349.     GLdouble center[3] = {0.0, 0.0, 0.0};
  350.  
  351.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
  352.     *sizeArray = radius;
  353.     displayList = findList (ICOSAWIRE, sizeArray, 1);
  354.  
  355.     if (displayList == 0) {
  356.     glNewList(makeModelPtr (ICOSAWIRE, sizeArray, 1),
  357.         GL_COMPILE_AND_EXECUTE);
  358.         icosahedron (center, radius, GL_LINE_LOOP);
  359.     glEndList();
  360.     }
  361.     else {
  362.     glCallList(displayList);
  363.     free (sizeArray);
  364.     }
  365. }
  366.  
  367. void auxSolidIcosahedron (GLdouble radius)
  368. {
  369.     GLdouble *sizeArray;
  370.     GLuint displayList;
  371.     GLdouble center[3] = {0.0, 0.0, 0.0};
  372.  
  373.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
  374.     *sizeArray = radius;
  375.     displayList = findList (ICOSASOLID, sizeArray, 1);
  376.  
  377.     if (displayList == 0) {
  378.     glNewList(makeModelPtr (ICOSASOLID, sizeArray, 1),
  379.         GL_COMPILE_AND_EXECUTE);
  380.         icosahedron (center, radius, GL_TRIANGLES);
  381.     glEndList();
  382.     }
  383.     else {
  384.     glCallList(displayList);
  385.     free (sizeArray);
  386.     }
  387. }
  388.  
  389. /*  Render wire frame or solid octahedra.  If no display list with
  390.  *  the current model size exists, create a new display list.
  391.  */
  392. void auxWireOctahedron (GLdouble radius)
  393. {
  394.     GLdouble *sizeArray;
  395.     GLuint displayList;
  396.     GLdouble center[3] = {0.0, 0.0, 0.0};
  397.  
  398.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
  399.     *sizeArray = radius;
  400.     displayList = findList (OCTAWIRE, sizeArray, 1);
  401.  
  402.     if (displayList == 0) {
  403.     glNewList(makeModelPtr (OCTAWIRE, sizeArray, 1),
  404.         GL_COMPILE_AND_EXECUTE);
  405.         octahedron (center, radius, GL_LINE_LOOP);
  406.     glEndList();
  407.     }
  408.     else {
  409.     glCallList(displayList);
  410.     free (sizeArray);
  411.     }
  412. }
  413.  
  414. void auxSolidOctahedron (GLdouble radius)
  415. {
  416.     GLdouble *sizeArray;
  417.     GLuint displayList;
  418.     GLdouble center[3] = {0.0, 0.0, 0.0};
  419.  
  420.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
  421.     *sizeArray = radius;
  422.     displayList = findList (OCTASOLID, sizeArray, 1);
  423.  
  424.     if (displayList == 0) {
  425.     glNewList(makeModelPtr (OCTASOLID, sizeArray, 1),
  426.         GL_COMPILE_AND_EXECUTE);
  427.         octahedron (center, radius, GL_TRIANGLES);
  428.     glEndList();
  429.     }
  430.     else {
  431.     glCallList(displayList);
  432.     free (sizeArray);
  433.     }
  434. }
  435.  
  436. /*  Render wire frame or solid tetrahedra.  If no display list with
  437.  *  the current model size exists, create a new display list.
  438.  */
  439. void auxWireTetrahedron (GLdouble radius)
  440. {
  441.     GLdouble *sizeArray;
  442.     GLuint displayList;
  443.     GLdouble center[3] = {0.0, 0.0, 0.0};
  444.  
  445.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
  446.     *sizeArray = radius;
  447.     displayList = findList (TETRAWIRE, sizeArray, 1);
  448.  
  449.     if (displayList == 0) {
  450.     glNewList(makeModelPtr (TETRAWIRE, sizeArray, 1),
  451.         GL_COMPILE_AND_EXECUTE);
  452.         tetrahedron (center, radius, GL_LINE_LOOP);
  453.     glEndList();
  454.     }
  455.     else {
  456.     glCallList(displayList);
  457.     free (sizeArray);
  458.     }
  459. }
  460.  
  461. void auxSolidTetrahedron (GLdouble radius)
  462. {
  463.     GLdouble *sizeArray;
  464.     GLuint displayList;
  465.     GLdouble center[3] = {0.0, 0.0, 0.0};
  466.  
  467.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
  468.     *sizeArray = radius;
  469.     displayList = findList (TETRASOLID, sizeArray, 1);
  470.  
  471.     if (displayList == 0) {
  472.     glNewList(makeModelPtr (TETRASOLID, sizeArray, 1),
  473.         GL_COMPILE_AND_EXECUTE);
  474.         tetrahedron (center, radius, GL_TRIANGLES);
  475.     glEndList();
  476.     }
  477.     else {
  478.     glCallList(displayList);
  479.     free (sizeArray);
  480.     }
  481. }
  482.  
  483. /*  Render wire frame or solid dodecahedra.  If no display list with
  484.  *  the current model size exists, create a new display list.
  485.  */
  486. void auxWireDodecahedron (GLdouble radius)
  487. {
  488.     GLdouble *sizeArray;
  489.     GLuint displayList;
  490.     GLdouble center[3] = {0.0, 0.0, 0.0};
  491.  
  492.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
  493.     *sizeArray = radius;
  494.     displayList = findList (DODECAWIRE, sizeArray, 1);
  495.  
  496.     if (displayList == 0) {
  497.     glNewList(makeModelPtr (DODECAWIRE, sizeArray, 1),
  498.         GL_COMPILE_AND_EXECUTE);
  499.         dodecahedron (center, radius/1.73, GL_LINE_LOOP);
  500.     glEndList();
  501.     }
  502.     else {
  503.     glCallList(displayList);
  504.     free (sizeArray);
  505.     }
  506. }
  507.  
  508. void auxSolidDodecahedron (GLdouble radius)
  509. {
  510.     GLdouble *sizeArray;
  511.     GLuint displayList;
  512.     GLdouble center[3] = {0.0, 0.0, 0.0};
  513.  
  514.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 1);
  515.     *sizeArray = radius;
  516.     displayList = findList (DODECASOLID, sizeArray, 1);
  517.  
  518.     if (displayList == 0) {
  519.     glNewList(makeModelPtr (DODECASOLID, sizeArray, 1),
  520.         GL_COMPILE_AND_EXECUTE);
  521.         dodecahedron (center, radius/1.73, GL_TRIANGLE_FAN);
  522.     glEndList();
  523.     }
  524.     else {
  525.     glCallList(displayList);
  526.     free (sizeArray);
  527.     }
  528. }
  529.  
  530. /*  Render wire frame or solid cones.  If no display list with
  531.  *  the current model size exists, create a new display list.
  532.  */
  533. void auxWireCone (GLdouble base, GLdouble height)
  534. {
  535.     GLUquadricObj *quadObj;
  536.     GLdouble *sizeArray, *tmp;
  537.     GLuint displayList;
  538.  
  539.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 2);
  540.     tmp = sizeArray;
  541.     *tmp++ = base;
  542.     *tmp++ = height;
  543.     displayList = findList (CONEWIRE, sizeArray, 2);
  544.  
  545.     if (displayList == 0) {
  546.     glNewList(makeModelPtr (CONEWIRE, sizeArray, 2),
  547.         GL_COMPILE_AND_EXECUTE);
  548.         quadObj = gluNewQuadric ();
  549.         gluQuadricDrawStyle (quadObj, GLU_LINE);
  550.         gluCylinder (quadObj, base, 0.0, height, 15, 10);
  551.     glEndList();
  552.     }
  553.     else {
  554.     glCallList(displayList);
  555.     free (sizeArray);
  556.     }
  557. }
  558.  
  559. void auxSolidCone (GLdouble base, GLdouble height)
  560. {
  561.     GLUquadricObj *quadObj;
  562.     GLdouble *sizeArray, *tmp;
  563.     GLuint displayList;
  564.  
  565.     sizeArray = (GLdouble *) malloc (sizeof (GLdouble) * 2);
  566.     tmp = sizeArray;
  567.     *tmp++ = base;
  568.     *tmp++ = height;
  569.     displayList = findList (CONEWIRE, sizeArray, 2);
  570.  
  571.     if (displayList == 0) {
  572.     glNewList(makeModelPtr (CONEWIRE, sizeArray, 2),
  573.         GL_COMPILE_AND_EXECUTE);
  574.         quadObj = gluNewQuadric ();
  575.         gluQuadricDrawStyle (quadObj, GLU_FILL);
  576.         gluQuadricNormals (quadObj, GLU_SMOOTH);
  577.         gluCylinder (quadObj, base, 0.0, height, 15, 10);
  578.     glEndList();
  579.     }
  580.     else {
  581.     glCallList(displayList);
  582.     free (sizeArray);
  583.     }
  584. }
  585.  
  586. /* Routines to build 3 dimensional solids, including:
  587.  *
  588.  * drawbox, doughnut, icosahedron, 
  589.  * octahedron, tetrahedron, dodecahedron.
  590.  */
  591.  
  592. /* drawbox:
  593.  *
  594.  * draws a rectangular box with the given x, y, and z ranges.  
  595.  * The box is axis-aligned.
  596.  */
  597. static void drawbox(GLdouble x0, GLdouble x1, GLdouble y0, GLdouble y1,
  598.     GLdouble z0, GLdouble z1, GLenum type)
  599. {
  600.     static GLdouble n[6][3] = {
  601.     {-1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {1.0, 0.0, 0.0},
  602.     {0.0, -1.0, 0.0}, {0.0, 0.0, 1.0}, {0.0, 0.0, -1.0}
  603.     };
  604.     static GLint faces[6][4] = {
  605.     { 0, 1, 2, 3 }, { 3, 2, 6, 7 }, { 7, 6, 5, 4 },
  606.     { 4, 5, 1, 0 }, { 5, 6, 2, 1 }, { 7, 4, 0, 3 }
  607.     };
  608.     GLdouble v[8][3], tmp;
  609.     GLint i;
  610.  
  611.     if (x0 > x1) {
  612.     tmp = x0; x0 = x1; x1 = tmp;
  613.     }
  614.     if (y0 > y1) {
  615.     tmp = y0; y0 = y1; y1 = tmp; 
  616.     }
  617.     if (z0 > z1) {
  618.     tmp = z0; z0 = z1; z1 = tmp; 
  619.     }
  620.     v[0][0] = v[1][0] = v[2][0] = v[3][0] = x0;
  621.     v[4][0] = v[5][0] = v[6][0] = v[7][0] = x1;
  622.     v[0][1] = v[1][1] = v[4][1] = v[5][1] = y0;
  623.     v[2][1] = v[3][1] = v[6][1] = v[7][1] = y1;
  624.     v[0][2] = v[3][2] = v[4][2] = v[7][2] = z0;
  625.     v[1][2] = v[2][2] = v[5][2] = v[6][2] = z1;
  626.  
  627.     for (i = 0; i < 6; i++) {
  628.     glBegin(type);
  629.     glNormal3dv(&n[i][0]);
  630.     glVertex3dv(&v[faces[i][0]][0]);
  631.     glNormal3dv(&n[i][0]);
  632.     glVertex3dv(&v[faces[i][1]][0]);
  633.     glNormal3dv(&n[i][0]);
  634.     glVertex3dv(&v[faces[i][2]][0]);
  635.     glNormal3dv(&n[i][0]);
  636.     glVertex3dv(&v[faces[i][3]][0]);
  637.     glEnd();
  638.     }
  639. }
  640.  
  641. /* doughnut:
  642.  *
  643.  * draws a doughnut, centered at (0, 0, 0) whose axis is aligned with
  644.  * the z-axis.  The doughnut's major radius is R, and minor radius is r.
  645.  */
  646.  
  647. static void doughnut(GLdouble r, GLdouble R, GLint nsides, GLint rings, GLenum type)
  648. {
  649.     int    i, j;
  650.     GLdouble    theta, phi, theta1, phi1;
  651.     GLdouble    p0[03], p1[3], p2[3], p3[3];
  652.     GLdouble    n0[3], n1[3], n2[3], n3[3];
  653.  
  654.     for (i = 0; i < rings; i++) {
  655.     theta = (GLdouble)i*2.0*PI/rings;
  656.     theta1 = (GLdouble)(i+1)*2.0*PI/rings;
  657.     for (j = 0; j < nsides; j++) {
  658.         phi = (GLdouble)j*2.0*PI/nsides;
  659.         phi1 = (GLdouble)(j+1)*2.0*PI/nsides;
  660.  
  661.         p0[0] = cos(theta)*(R + r*cos(phi));
  662.         p0[1] = -sin(theta)*(R + r*cos(phi));
  663.         p0[2] = r*sin(phi);
  664.  
  665.         p1[0] = cos(theta1)*(R + r*cos(phi));
  666.         p1[1] = -sin(theta1)*(R + r*cos(phi));
  667.         p1[2] = r*sin(phi);
  668.  
  669.         p2[0] = cos(theta1)*(R + r*cos(phi1));
  670.         p2[1] = -sin(theta1)*(R + r*cos(phi1));
  671.         p2[2] = r*sin(phi1);
  672.  
  673.         p3[0] = cos(theta)*(R + r*cos(phi1));
  674.         p3[1] = -sin(theta)*(R + r*cos(phi1));
  675.         p3[2] = r*sin(phi1);
  676.  
  677.         n0[0] = cos(theta)*(cos(phi));
  678.         n0[1] = -sin(theta)*(cos(phi));
  679.         n0[2] = sin(phi);
  680.  
  681.         n1[0] = cos(theta1)*(cos(phi));
  682.         n1[1] = -sin(theta1)*(cos(phi));
  683.         n1[2] = sin(phi);
  684.  
  685.         n2[0] = cos(theta1)*(cos(phi1));
  686.         n2[1] = -sin(theta1)*(cos(phi1));
  687.         n2[2] = sin(phi1);
  688.  
  689.         n3[0] = cos(theta)*(cos(phi1));
  690.         n3[1] = -sin(theta)*(cos(phi1));
  691.         n3[2] = sin(phi1);
  692.  
  693.         m_xformpt(p0, p0, n0, n0);
  694.         m_xformpt(p1, p1, n1, n1);
  695.         m_xformpt(p2, p2, n2, n2);
  696.         m_xformpt(p3, p3, n3, n3);
  697.  
  698.         glBegin(type);
  699.         glNormal3dv(n3);
  700.         glVertex3dv(p3);
  701.         glNormal3dv(n2);
  702.         glVertex3dv(p2);
  703.         glNormal3dv(n1);
  704.         glVertex3dv(p1);
  705.         glNormal3dv(n0);
  706.         glVertex3dv(p0);
  707.         glEnd();
  708.     }
  709.     }
  710. }
  711.  
  712. /* octahedron data: The octahedron produced is centered 
  713.  * at the origin and has radius 1.0 
  714.  */
  715. static GLdouble odata[6][3] = {
  716.   {1.0, 0.0, 0.0},
  717.   {-1.0, 0.0, 0.0},
  718.   {0.0, 1.0, 0.0},
  719.   {0.0, -1.0, 0.0},
  720.   {0.0, 0.0, 1.0},
  721.   {0.0, 0.0, -1.0}
  722. };
  723.  
  724. static int ondex[8][3] = {
  725.     {0, 4, 2}, {1, 2, 4}, {0, 3, 4}, {1, 4, 3},
  726.     {0, 2, 5}, {1, 5, 2}, {0, 5, 3}, {1, 3, 5}
  727. };
  728.  
  729. /* tetrahedron data: */
  730.  
  731. #define T    1.73205080756887729
  732.  
  733. static GLdouble tdata[4][3] = {
  734.     {T, T, T}, {T, -T, -T}, {-T, T, -T}, {-T, -T, T}
  735. };
  736.  
  737. static int tndex[4][3] = {
  738.     {0, 1, 3}, {2, 1, 0}, {3, 2, 0}, {1, 2, 3}
  739. };
  740.  
  741. /* icosahedron data: These numbers are rigged to 
  742.  * make an icosahedron of radius 1.0 
  743.  */
  744.  
  745. #define X .525731112119133606
  746. #define Z .850650808352039932
  747.  
  748. static GLdouble idata[12][3] = {
  749.   {-X, 0.0, Z},
  750.   {X, 0.0, Z},
  751.   {-X, 0.0, -Z},
  752.   {X, 0.0, -Z},
  753.   {0.0, Z, X},
  754.   {0.0, Z, -X},
  755.   {0.0, -Z, X},
  756.   {0.0, -Z, -X},
  757.   {Z, X, 0.0},
  758.   {-Z, X, 0.0},
  759.   {Z, -X, 0.0},
  760.   {-Z, -X, 0.0},
  761. };
  762.  
  763. static int iindex[20][3] = {
  764.     {0, 4, 1},    {0, 9, 4},
  765.     {9, 5, 4},    {4, 5, 8},
  766.     {4, 8, 1},    {8, 10, 1},
  767.     {8, 3, 10},    {5, 3, 8},
  768.     {5, 2, 3},    {2, 7, 3},
  769.     {7, 10, 3},    {7, 6, 10},
  770.     {7, 11, 6},    {11, 0, 6},
  771.     {0, 1, 6},    {6, 1, 10},
  772.     {9, 0, 11},    {9, 11, 2},
  773.     {9, 2, 5},    {7, 2, 11},
  774. };
  775.  
  776. /* icosahedron:
  777.  *
  778.  * Draws an icosahedron with center at p0 having the
  779.  * given radius.
  780.  */
  781.  
  782. static void icosahedron(GLdouble p0[3], GLdouble radius, GLenum shadeType)
  783. {
  784.     int i;
  785.  
  786.     for (i = 0; i < 20; i++)
  787.     drawtriangle(i, 0, 1, p0, radius, shadeType, 0);
  788. }
  789.  
  790. /* octahedron:
  791.  *
  792.  * Draws an octahedron with center at p0 having the
  793.  * given radius.
  794.  */
  795. static void octahedron(GLdouble p0[3], GLdouble radius, GLenum shadeType)
  796. {
  797.     int i;
  798.  
  799.     for (i = 0; i < 8; i++)
  800.     drawtriangle(i, 1, 1, p0, radius, shadeType, 0);
  801. }
  802.  
  803. /* tetrahedron:
  804.  *
  805.  * Draws an tetrahedron with center at p0 having the
  806.  * given radius.
  807.  */
  808.  
  809. static void tetrahedron(GLdouble p0[3], GLdouble radius, GLenum shadeType)
  810. {
  811.     int i;
  812.  
  813.     for (i = 0; i < 4; i++)
  814.     drawtriangle(i, 2, 1, p0, radius, shadeType, 0);
  815. }
  816.  
  817. static void subdivide(int depth, GLdouble *v0, GLdouble *v1, GLdouble *v2,
  818.     GLdouble p0[3], GLdouble radius, GLenum shadeType, int avnormal)
  819. {
  820.     GLdouble w0[3], w1[3], w2[3];
  821.     GLdouble l;
  822.     int i, j, k, n;
  823.  
  824.     for (i = 0; i < depth; i++)
  825.     for (j = 0; i + j < depth; j++) {
  826.         k = depth - i - j;
  827.         for (n = 0; n < 3; n++) {
  828.         w0[n] = (i*v0[n] + j*v1[n] + k*v2[n])/depth;
  829.         w1[n] = ((i+1)*v0[n] + j*v1[n] + (k-1)*v2[n])/depth;
  830.         w2[n] = (i*v0[n] + (j+1)*v1[n] + (k-1)*v2[n])/depth;
  831.         }
  832.         l = sqrt(w0[0]*w0[0] + w0[1]*w0[1] + w0[2]*w0[2]);
  833.         w0[0] /= l; w0[1] /= l; w0[2] /= l;
  834.         l = sqrt(w1[0]*w1[0] + w1[1]*w1[1] + w1[2]*w1[2]);
  835.         w1[0] /= l; w1[1] /= l; w1[2] /= l;
  836.         l = sqrt(w2[0]*w2[0] + w2[1]*w2[1] + w2[2]*w2[2]);
  837.         w2[0] /= l; w2[1] /= l; w2[2] /= l;
  838.         recorditem(w1, w0, w2, p0, radius, shadeType, avnormal);
  839.     }
  840.     for (i = 0; i < depth-1; i++)
  841.     for (j = 0; i + j < depth-1; j++) {
  842.         k = depth - i - j;
  843.         for (n = 0; n < 3; n++) {
  844.         w0[n] = ((i+1)*v0[n] + (j+1)*v1[n] + (k-2)*v2[n])/depth;
  845.         w1[n] = ((i+1)*v0[n] + j*v1[n] + (k-1)*v2[n])/depth;
  846.         w2[n] = (i*v0[n] + (j+1)*v1[n] + (k-1)*v2[n])/depth;
  847.         }
  848.         l = sqrt(w0[0]*w0[0] + w0[1]*w0[1] + w0[2]*w0[2]);
  849.         w0[0] /= l; w0[1] /= l; w0[2] /= l;
  850.         l = sqrt(w1[0]*w1[0] + w1[1]*w1[1] + w1[2]*w1[2]);
  851.         w1[0] /= l; w1[1] /= l; w1[2] /= l;
  852.         l = sqrt(w2[0]*w2[0] + w2[1]*w2[1] + w2[2]*w2[2]);
  853.         w2[0] /= l; w2[1] /= l; w2[2] /= l;
  854.         recorditem(w0, w1, w2, p0, radius, shadeType, avnormal);
  855.     }
  856. }
  857.  
  858. static void drawtriangle(int i, int geomType, int depth,
  859.     GLdouble p0[3], GLdouble radius, GLenum shadeType, int avnormal)
  860. {
  861.     GLdouble *x0, *x1, *x2;
  862.  
  863.     switch (geomType) {
  864.     case 0:    /* icosahedron */
  865.         x0 = &idata[iindex[i][0]][0];
  866.         x1 = &idata[iindex[i][1]][0];
  867.         x2 = &idata[iindex[i][2]][0];
  868.         break;
  869.     case 1: /* octahedron */
  870.         x0 = &odata[ondex[i][0]][0];
  871.         x1 = &odata[ondex[i][1]][0];
  872.         x2 = &odata[ondex[i][2]][0];
  873.         break;
  874.     case 2: /* tetrahedron */
  875.         x0 = &tdata[tndex[i][0]][0];
  876.         x1 = &tdata[tndex[i][1]][0];
  877.         x2 = &tdata[tndex[i][2]][0];
  878.         break;
  879.     }
  880.     subdivide(depth, x0, x1, x2, p0, radius, shadeType, avnormal);
  881. }
  882.  
  883. static void recorditem(GLdouble *n1, GLdouble *n2, GLdouble *n3,
  884.     GLdouble center[3], GLdouble radius, GLenum shadeType, int avnormal)
  885. {
  886.     GLdouble p1[3], p2[3], p3[3], q0[3], q1[3], n11[3], n22[3], n33[3];
  887.     int    i;
  888.  
  889.     for (i = 0; i < 3; i++) {
  890.     p1[i] = n1[i]*radius + center[i];
  891.     p2[i] = n2[i]*radius + center[i];
  892.     p3[i] = n3[i]*radius + center[i];
  893.     }
  894.     if (avnormal == 0) {
  895.     diff3(p1, p2, q0);
  896.     diff3(p2, p3, q1);
  897.     crossprod(q0, q1, q1);
  898.     normalize(q1);
  899.     m_xformpt(p1, p1, q1, n11);
  900.     m_xformptonly(p2, p2);
  901.     m_xformptonly(p3, p3);
  902.  
  903.     glBegin (shadeType);
  904.     glNormal3dv(n11);
  905.     glVertex3dv(p1);
  906.     glVertex3dv(p2);
  907.     glVertex3dv(p3);
  908.     glEnd();
  909.     return;
  910.     }
  911.     m_xformpt(p1, p1, n1, n11);
  912.     m_xformpt(p2, p2, n2, n22);
  913.     m_xformpt(p3, p3, n3, n33);
  914.  
  915.     glBegin (shadeType);
  916.     glNormal3dv(n11);
  917.     glVertex3dv(p1);
  918.     glNormal3dv(n22);
  919.     glVertex3dv(p2);
  920.     glNormal3dv(n33);
  921.     glVertex3dv(p3);
  922.     glEnd();
  923. }
  924.  
  925. static GLdouble dodec[20][3];
  926.  
  927. static void initdodec()
  928. {
  929.     GLdouble alpha, beta;
  930.  
  931.     alpha = sqrt(2.0/(3.0 + sqrt(5.0)));
  932.     beta = 1.0 + sqrt(6.0/(3.0 + sqrt(5.0)) - 2.0 + 2.0*sqrt(2.0/(3.0 +
  933.                                 sqrt(5.0))));
  934.     dodec[0][0] = -alpha; dodec[0][1] = 0; dodec[0][2] = beta;
  935.     dodec[1][0] = alpha; dodec[1][1] = 0; dodec[1][2] = beta;
  936.     dodec[2][0] = -1; dodec[2][1] = -1; dodec[2][2] = -1;
  937.     dodec[3][0] = -1; dodec[3][1] = -1; dodec[3][2] = 1;
  938.     dodec[4][0] = -1; dodec[4][1] = 1; dodec[4][2] = -1;
  939.     dodec[5][0] = -1; dodec[5][1] = 1; dodec[5][2] = 1;
  940.     dodec[6][0] = 1; dodec[6][1] = -1; dodec[6][2] = -1;
  941.     dodec[7][0] = 1; dodec[7][1] = -1; dodec[7][2] = 1;
  942.     dodec[8][0] = 1; dodec[8][1] = 1; dodec[8][2] = -1;
  943.     dodec[9][0] = 1; dodec[9][1] = 1; dodec[9][2] = 1;
  944.     dodec[10][0] = beta; dodec[10][1] = alpha; dodec[10][2] = 0;
  945.     dodec[11][0] = beta; dodec[11][1] = -alpha; dodec[11][2] = 0;
  946.     dodec[12][0] = -beta; dodec[12][1] = alpha; dodec[12][2] = 0;
  947.     dodec[13][0] = -beta; dodec[13][1] = -alpha; dodec[13][2] = 0;
  948.     dodec[14][0] = -alpha; dodec[14][1] = 0; dodec[14][2] = -beta;
  949.     dodec[15][0] = alpha; dodec[15][1] = 0; dodec[15][2] = -beta;
  950.     dodec[16][0] = 0; dodec[16][1] = beta; dodec[16][2] = alpha;
  951.     dodec[17][0] = 0; dodec[17][1] = beta; dodec[17][2] = -alpha;
  952.     dodec[18][0] = 0; dodec[18][1] = -beta; dodec[18][2] = alpha;
  953.     dodec[19][0] = 0; dodec[19][1] = -beta; dodec[19][2] = -alpha;
  954. }
  955.  
  956. /* dodecahedron:
  957.  *
  958.  * Draws an dodecahedron with center at 0.0. The radius
  959.  * is sqrt(3).
  960.  */
  961. static void dodecahedron(GLdouble center[3], GLdouble sc, GLenum type)
  962. {
  963.     static int inited = 0;
  964.  
  965.     if ( inited == 0) {
  966.     inited = 1;
  967.     initdodec();
  968.     }
  969.     m_pushmatrix();
  970.     m_translate(center[0], center[1], center[2]);
  971.     m_scale(sc, sc, sc);
  972.     pentagon(0, 1, 9, 16, 5, type);
  973.     pentagon(1, 0, 3, 18, 7, type);
  974.     pentagon(1, 7, 11, 10, 9, type);
  975.     pentagon(11, 7, 18, 19, 6, type);
  976.     pentagon(8, 17, 16, 9, 10, type);
  977.     pentagon(2, 14, 15, 6, 19, type);
  978.     pentagon(2, 13, 12, 4, 14, type);
  979.     pentagon(2, 19, 18, 3, 13, type);
  980.     pentagon(3, 0, 5, 12, 13, type);
  981.     pentagon(6, 15, 8, 10, 11, type);
  982.     pentagon(4, 17, 8, 15, 14, type);
  983.     pentagon(4, 12, 5, 16, 17, type);
  984.     m_popmatrix();
  985. }
  986.  
  987. static void pentagon(int a, int b, int c, int d, int e, GLenum shadeType)
  988. {
  989.     GLdouble n0[3], d1[3], d2[3], d3[3], d4[3], d5[3], nout[3];
  990.  
  991.     diff3(&dodec[a][0], &dodec[b][0], d1);
  992.     diff3(&dodec[b][0], &dodec[c][0], d2);
  993.     crossprod(d1, d2, n0);
  994.     normalize(n0);
  995.     m_xformpt(&dodec[a][0], d1, n0, nout);
  996.     m_xformptonly(&dodec[b][0], d2);
  997.     m_xformptonly(&dodec[c][0], d3);
  998.     m_xformptonly(&dodec[d][0], d4);
  999.     m_xformptonly(&dodec[e][0], d5);
  1000.  
  1001.     glBegin (shadeType);
  1002.     glNormal3dv(nout);
  1003.     glVertex3dv(d1);
  1004.     glVertex3dv(d2);
  1005.     glVertex3dv(d3);
  1006.     glVertex3dv(d4);
  1007.     glVertex3dv(d5);
  1008.     glEnd();
  1009. }
  1010.  
  1011. /*    linked lists--display lists for each different 
  1012.  *    type of geometric objects.  The linked list is 
  1013.  *    searched, until an object of the requested
  1014.  *    size is found.  If no geometric object of that size
  1015.  *    has been previously made, a new one is created.
  1016.  */
  1017. GLuint findList (int lindex, GLdouble *paramArray, int size) 
  1018. {
  1019.     MODELPTR endList;
  1020.     int found = 0;
  1021.     
  1022.     endList = lists[lindex];
  1023.     while (endList != NULL) {
  1024.     if (compareParams (endList->params, paramArray, size))
  1025.         return (endList->list);
  1026.     endList = endList->ptr;
  1027.     }
  1028. /*  if not found, return 0 and calling routine should
  1029.  *  make a new list    
  1030.  */
  1031.     return (0);
  1032. }
  1033.  
  1034. int compareParams (GLdouble *oneArray, GLdouble *twoArray, int size) 
  1035. {
  1036.     int i;
  1037.     int matches = 1;
  1038.  
  1039.     for (i = 0; (i < size) && matches; i++) {
  1040.     if (*oneArray++ != *twoArray++)
  1041.         matches = 0;
  1042.     }
  1043.     return (matches);
  1044. }
  1045.  
  1046. GLuint makeModelPtr (int lindex, GLdouble *sizeArray, int count)
  1047. {
  1048.     MODELPTR newModel;
  1049.  
  1050.     newModel = (MODELPTR) malloc (sizeof (MODEL));
  1051.     newModel->list = glGenLists (1);
  1052.     newModel->numParam = count;
  1053.     newModel->params = sizeArray;
  1054.     newModel->ptr = lists[lindex];
  1055.     lists[lindex] = newModel;
  1056.  
  1057.     return (newModel->list);
  1058. }
  1059.